#include "hash.h"

pthread_mutex_t hash_mutex = PTHREAD_MUTEX_INITIALIZER;

// hash表数组 数组中存储的是指针
hashtable_t **create_hashtable()
{
    hashtable_t **h = malloc(sizeof(hashtable_t *) * HTABLE_LEN);
    memset(h, 0, sizeof(hashtable_t *) * HTABLE_LEN);

    // 数组中所有指针初始化为NULL
    for (int i = 0; i < HTABLE_LEN; i++)
    {
        h[i] = NULL;
    }

    return h;
}

// hash算法 将字符串中的每个字符对应的ASCII相加
int hashcode(const char *string)
{
    int code = 0;

    while (*string)
    {
        code += *string++;
    }

    return code;
}

void insert_data_hash(hashtable_t **h, char *key, datatype_t value)
{
    int code = hashcode(key);
    int index = code % HTABLE_LEN; // 哈希函数
    hashtable_t *p = h[index];

    pthread_mutex_lock(&hash_mutex);
    while (p != NULL && p->data.pid <= value.pid)
    {
        p = p->next;
    }

    hashtable_t *temp = (hashtable_t *)malloc(sizeof(hashtable_t));
    if (temp == NULL)
    {
        pthread_mutex_unlock(&hash_mutex);
        return;
    }

    temp->data = value;
    temp->next = p;

    // 相同冲突的结点按从小到大顺序放到链表
    if (h[index] == NULL || h[index]->data.pid > value.pid)
    {
        h[index] = temp; // 插入链表头部
    }
    else
    {
        // 找到前一个结点
        hashtable_t *pre = h[index];
        while (pre->next != NULL && pre->next->data.pid <= value.pid)
        {
            if (pre->next->data.pid == value.pid)
            {
                // 主题与pid相等 为同一进程订阅了同一主题
                return;
            }
            pre = pre->next;
        }

        pre->next = temp;
    }

    pthread_mutex_unlock(&hash_mutex);
}

int search_hash(hashtable_t **h, char *key, int result[])
{
    int cnt = 0;
    int code = hashcode(key);
    int index = code % HTABLE_LEN;
    hashtable_t **p = NULL;

    pthread_mutex_lock(&hash_mutex);
    for (p = &h[index]; *p != NULL; p = &(*p)->next)
    {
        printf("%s,%s,%d--key:%s data:%s\n", __FILE__, __FUNCTION__, __LINE__, key, (*p)->data.topic);

        // 根据数据区主题查找
        if (strcmp(key, (*p)->data.topic) == 0)
        {
            printf("%s,%s,%d,%s\n", __FILE__, __FUNCTION__, __LINE__, (*p)->data.topic);

            // 存放数据区id
            result[cnt++] = (*p)->data.pid;
        }
    }
    pthread_mutex_unlock(&hash_mutex);

    return cnt; // 查询到数据区个数
}

void print_hash(hashtable_t **h)
{
    hashtable_t **p = NULL;
    for (int i = 0; i < HTABLE_LEN; i++)
    {
        printf("index:%d:", i);

        for (p = &h[i]; *p != NULL; p = &((*p)->next))
        {
            printf("%s ", (*p)->data.topic);
        }
        putchar('\n');
    }
}
